package com.pan.service.impl;

import com.pan.dao.coupon.CouponDao;
import com.pan.dao.coupon.CouponSelectDao;
import com.pan.dao.couponRelationCategory.CouponRelationCategoryDao;
import com.pan.dao.couponRelationCategory.CouponRelationCategorySelectDao;
import com.pan.dao.couponRelationGoods.CouponRelationGoodsDao;
import com.pan.dao.couponRelationGoods.CouponRelationGoodsSelectDao;
import com.pan.entity.*;
import com.pan.enume.ResultEnum;
import com.pan.service.CouponService;
import com.pan.tools.ConvertObject;
import com.pan.tools.RedisTools;
import com.pan.vo.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Timestamp;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;


@Service("couponService")
public class CouponServiceImpl implements CouponService {


    @Resource
    private RedisTools redisTools;

    @Resource
    private CouponDao couponDao;

    @Resource
    private CouponSelectDao couponSelectDao;

    @Resource
    private CouponRelationCategorySelectDao couponRelationCategorySelectDao;

    @Resource
    private CouponRelationGoodsSelectDao couponRelationGoodsSelectDao;

    @Resource
    private CouponRelationGoodsDao couponRelationGoodsDao;

    @Resource
    private CouponRelationCategoryDao couponRelationCategoryDao;


    @Transactional
    @Override
    public Result insert(String adminTicket, CouponCreateVo couponCreateVo){
        Coupon coupon = ConvertObject.convertObject(new Coupon(),couponCreateVo);
        Timestamp nowTime = new Timestamp(System.currentTimeMillis());
        Result resultAdminId = redisTools.hget("admin:"+adminTicket,"id");
        Long adminId = Long.parseLong( (String) resultAdminId.getData());
        coupon.setCreateAdmin(adminId).setCreateDate(nowTime)
                .setUseCount(0).setReceiveCount(0);
        Long id = couponDao.insert(coupon);
        List<RelationGoodsVo> goodsList = couponCreateVo.getGoodsList();
        List<RelationCategoryVo> categoryList = couponCreateVo.getCategoryList();

        if (goodsList!=null&&goodsList.size()!=0) {
            List<CouponRelationGoods> insertGoodsList = goodsList
                    .stream().map(vo -> ConvertObject.convertObject(new CouponRelationGoods(), vo).setCouponId(id))
                    .collect(Collectors.toList());
            couponRelationGoodsDao.insertList(insertGoodsList);
        }
        if (categoryList!=null&&categoryList.size()!=0) {
            List<CouponRelationCategory> insertCategoryList = categoryList
                    .stream().map(vo -> ConvertObject.convertObject(new CouponRelationCategory(), vo).setCouponId(id))
                    .collect(Collectors.toList());
            couponRelationCategoryDao.insertList(insertCategoryList);
        }
        Result result = new Result<>(ResultEnum.SUCCESS);
        return result;
    }

    @Override
    public Result<List<Coupon>> select(){
        List<Coupon> li = couponDao.select();
        Long now = System.currentTimeMillis();
        li = li.stream().filter(i->i.getEndDate().getTime()>now).collect(Collectors.toList());
        Result result = new Result(ResultEnum.SUCCESS,li);
        return result;
    }

    @Override
    public Result<CouponShowVo> selectShowVoById(Long id){
        Coupon coupon = couponSelectDao.selectById(id);
        if (coupon==null){
            return new Result<>(ResultEnum.NOT_FOUND_ERROR);
        }
        CouponShowVo couponShowVo = ConvertObject.convertObject(new CouponShowVo(),coupon);
        List<RelationCategoryVo> categoryList = couponRelationCategoryDao.selectByCouponId(id);
        List<RelationGoodsVo> goodsList = couponRelationGoodsDao.selectByCouponId(id);
        couponShowVo.setCategoryList(categoryList)
                .setGoodsList(goodsList);
        return new Result<>(ResultEnum.SUCCESS, couponShowVo);
    }

    private <T> Integer indexOf(T[] arr,T target){
        for (int i=0;i<arr.length;i++){
            if (arr[i].equals(target)){
                return i;
            }
        }
        return null;
    }

    /**
     *
     * @param id 这个id是 categoryId 或者 goodsId
     * @param type 类型名称 goods 或者 category
     * @return
     */
    @Override
    public Result<List<Coupon>> selectByCategoryIdOrGoodsId(Long id,String type)
            throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, ClassNotFoundException {
        String firstUp = type.substring(0,1).toUpperCase()+type.substring(1);
        Field[] fields = this.getClass().getDeclaredFields();
        String[] parameterNames = Arrays.stream(fields).map(Field::getName).toArray(String[]::new);
        Integer index = indexOf(parameterNames,"couponRelation"+type+"SelectDao");
        Field field = fields[index];
        Object relationSelectDao = field.get(this);
        String methodName = "selectBy"+firstUp+"Id";
        Method method = relationSelectDao.getClass().getMethod(methodName, Long.class);
        List<Object> relationList = (List<Object>) method.invoke(relationSelectDao,id);
        Class relationClass = Class.forName("com.pan.vo.Relation"+firstUp+"Vo");
        Method getCouponIdMethod = relationClass.getMethod("getCouponId");
        Long nowTime = System.currentTimeMillis();
        List<Coupon> couponsList =  relationList.stream().map(relation -> {
                    Long couponId = null;
                    try {
                        couponId = (Long) getCouponIdMethod.invoke(relation);
                    } catch (IllegalAccessException | InvocationTargetException e) {
                        throw new RuntimeException(e);
                    }
                    Coupon coupon = couponSelectDao.selectById(couponId);
            return coupon;
        }).filter(coupon -> coupon.getEndDate().getTime()>nowTime)
                .collect(Collectors.toList());
        return new Result(ResultEnum.SUCCESS,couponsList);
    }



    @Override
    public Result<List<Coupon>> selectByNoStart(String adminTicket){
        List<Coupon> coupons = couponDao.selectByNoStart();
        Result result = new Result(ResultEnum.SUCCESS,coupons);
        return result;
    }


}
